/*******************************************************************************
* Project: QSAR(Cute Software Architecture) 
*
* Copyright: Copyright(C) 2024 by YuetingBen, All Rights Reserved
*
* File name: DcmDspSvc27.c
*
* Brief: ;
*
* Author: Yueting.Ben
*
* Module: Dcm
*
* Revision:
* ------------------------------------------------------------------------------
* v0.1: 
* --Yueting.Ben, 2024-03-22 
* --Initial release

*******************************************************************************/

/** HEADER FILES **/
#include "DcmDspSvc27.h"
#include "DcmDsp.h"


/** MACRO DEFINITION **/


/** TYPEDEF DEFINITION **/
typedef struct
{
    uint8 AttemptCounter;
}DcmDspSvc27_InfoType;

/** LOCAL DATA DECLARATION **/


/** GLOBAL DATA DECLARATION **/


/** LOCAL FUNCTION DECLARATION **/


/** GLOBAL FUNCTION DECLARATION **/
Std_ReturnType DcmDsp_SecurityCheck(
    DcmDspSecurityType* secLevelPrt
);

Std_ReturnType DcmDsp_Svc27_01_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
);

Std_ReturnType DcmDsp_Svc27_02_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
);

Std_ReturnType DcmDsp_Svc27_03_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
);

Std_ReturnType DcmDsp_Svc27_04_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
);

Std_ReturnType DcmDsp_Svc27_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
);


/** LOCAL DATA **/
static DcmDspSvc27_InfoType DcmDspSvc27Info;

/** GLOBAL DATA **/


/** LOCAL FUNCTION **/


/** GLOBAL FUNCTION **/

/*******************************************************************************
* -Name            DcmDsp_SecurityCheck
* -Brief           None
* -Details         None
* -Param[in]       OpStatus: The operations status        
* -Param[in, out]  pMsgContext: Message context 
* -Param[out]      ErrorCode: Negative response code
* -Return          E_OK:          
*                  E_NOT_OK: 
*                  DCM_E_PENDING:
*                  DCM_E_FORCE_RCRRP:
*******************************************************************************/
Std_ReturnType DcmDsp_SecurityCheck(
    DcmDspSecurityType* secLevelPrt
)
{
    Std_ReturnType retVal = E_OK;
    Dcm_SecLevelType secLevel;
    uint8 secIndex;

    DcmDsl_GetSecurityLevel(&secLevel);
    for(secIndex = 0u; secIndex < DCM_SEC_LEV_MAX; secIndex++)
    {
        if(NULL_PTR != secLevelPrt->DcmDspSecurityCfg[secIndex])
        {
            if((secLevel == secLevelPrt->DcmDspSecurityCfg[secIndex]->DcmDspSecurityLevel)
              || (DCM_SEC_LEV_LOCKED == secLevelPrt->DcmDspSecurityCfg[secIndex]->DcmDspSecurityLevel))
            {
                retVal = E_OK;
                break;
            }
            else
            {
                retVal = E_NOT_OK;
            }
        }
    }
    
    return(retVal);
}

/*******************************************************************************
* -Name            DcmDsp_Svc27_01_Processor
* -Brief           None
* -Details         None
* -Param[in]       OpStatus: The operations status        
* -Param[in, out]  pMsgContext: Message context 
* -Param[out]      ErrorCode: Negative response code
* -Return          E_OK:          
*                  E_NOT_OK: 
*                  DCM_E_PENDING:
*                  DCM_E_FORCE_RCRRP:
*******************************************************************************/
Std_ReturnType DcmDsp_Svc27_01_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
)
{
    Std_ReturnType retVal = E_OK;
    Dcm_SecLevelType secLevel;
    uint8 secIndex;
    DcmDspSvc27_InfoType* dcmDspSvc27InfoPtr = (DcmDspSvc27_InfoType*)&DcmDspSvc27Info;
    DcmDspSecurityRowType* secCfgPtr;

    switch(Dcm_GetProgress(pMsgContext))
    {
        case DCM_PROGRESS_INITIAL:
        {
            retVal = DCM_E_PENDING;
            Dcm_SetProgress(pMsgContext, DCM_PROGRESS_LENGTH_FORMAT_CHECK);
            break;
        }
        case DCM_PROGRESS_LENGTH_FORMAT_CHECK:
        {
            retVal = DCM_E_PENDING;
            if(DCMDSPSVC27_REQ_2701_DATA_MINLENGTH == pMsgContext->reqDataLen)
            {
                Dcm_SetProgress(pMsgContext, DCM_PROGRESS_IMPLEMENTATION);
            }
            else
            {
                *ErrorCode = DCM_E_INCORRECTMES_SAGELENGTHORINVALID_FORMAT;
                retVal = E_NOT_OK;
            }
            break;
        }
        case DCM_PROGRESS_IMPLEMENTATION:
        {
            secLevel = (Dcm_SecLevelType)((pMsgContext->reqData[DCM_REQ_ACCESS_TYPE_INDEX] + 1) / 2);
            
            for(secIndex = 0u; secIndex < DCM_SEC_LEV_MAX; secIndex++)
            {
                if(secLevel == DcmDspSecurityCfg[secIndex]->DcmDspSecurityLevel)
                {
                    secCfgPtr = (DcmDspSecurityRowType*)(DcmDspSecurityCfg[secIndex]);

                    if(DCM_NULL_PROCESSOR != secCfgPtr->DcmDspSecurityGetSeedFnc)
                    {
                        retVal = secCfgPtr->DcmDspSecurityGetSeedFnc(OpStatus, &pMsgContext->resData[DCM_RES_SEED_START_INDEX], ErrorCode);
                        pMsgContext->resDataLen = 1 + secCfgPtr->DcmDspSecuritySeedSize;
                    }

                    break;
                }
            }
        }
    }
    return(retVal);
}

/*******************************************************************************
* -Name            DcmDsp_Svc27_02_Processor
* -Brief           None
* -Details         None
* -Param[in]       OpStatus: The operations status        
* -Param[in, out]  pMsgContext: Message context 
* -Param[out]      ErrorCode: Negative response code
* -Return          E_OK:          
*                  E_NOT_OK: 
*                  DCM_E_PENDING:
*                  DCM_E_FORCE_RCRRP:
*******************************************************************************/
Std_ReturnType DcmDsp_Svc27_02_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
)
{
    Std_ReturnType retVal = E_OK;
    Dcm_SecLevelType secLevel;
    DcmDspSecurityRowType* secCfgPtr;
    uint8 secIndex;
    DcmDspSvc27_InfoType* dcmDspSvc27InfoPtr = (DcmDspSvc27_InfoType*)&DcmDspSvc27Info;
    uint8 timerExpiredStatus;


    switch(Dcm_GetProgress(pMsgContext))
    {
        case DCM_PROGRESS_INITIAL:
        {
            retVal = DCM_E_PENDING;
            Dcm_SetProgress(pMsgContext, DCM_PROGRESS_LENGTH_FORMAT_CHECK);
            break;
        }
        case DCM_PROGRESS_LENGTH_FORMAT_CHECK:
        {
            retVal = DCM_E_PENDING;
            if(DCMDSPSVC27_REQ_2702_DATA_MINLENGTH == pMsgContext->reqDataLen)
            {
                Dcm_SetProgress(pMsgContext, DCM_PROGRESS_IMPLEMENTATION);
            }
            else
            {
                *ErrorCode = DCM_E_INCORRECTMES_SAGELENGTHORINVALID_FORMAT;
                retVal = E_NOT_OK;
            }
            break;
        }
        case DCM_PROGRESS_IMPLEMENTATION:
        {
            secLevel = (Dcm_SecLevelType)((pMsgContext->reqData[DCM_REQ_ACCESS_TYPE_INDEX] + 1) / 2);

            for(secIndex = 0u; secIndex < DCM_SEC_LEV_MAX; secIndex++)
            {
                if(secLevel == DcmDspSecurityCfg[secIndex]->DcmDspSecurityLevel)
                {
                    secCfgPtr = (DcmDspSecurityRowType*)(DcmDspSecurityCfg[secIndex]);

                    Tm_GetTimerExpiredStatus(TmConf_TimerChannel_DcmDspSvc27SecurityDelayTimer, (uint8*)&timerExpiredStatus);
                    if(dcmDspSvc27InfoPtr->AttemptCounter >= secCfgPtr->DcmDspSecurityNumAttDelay)
                    {
                        if(SET != timerExpiredStatus)
                        {
                            *ErrorCode = DCM_E_REQUIREDTIMEDELAYNOTEXPIRED;
                            retVal = E_NOT_OK;
                            return(retVal);
                        }
                    }

                    if(DCM_NULL_PROCESSOR != secCfgPtr->DcmDspSecurityCompareKeyFnc)
                    {
                        retVal = secCfgPtr->DcmDspSecurityCompareKeyFnc(&pMsgContext->reqData[DCM_REQ_DATA_RECORD_START_INDEX], OpStatus, ErrorCode);
                        if(E_OK == retVal)
                        {
                            DcmDsl_SetSecurityLevel(secCfgPtr->DcmDspSecurityLevel);
                            dcmDspSvc27InfoPtr->AttemptCounter = 0u;
                        }
                        else
                        {
                            *ErrorCode = DCM_E_INVALIDKEY;
                            if(dcmDspSvc27InfoPtr->AttemptCounter < secCfgPtr->DcmDspSecurityNumAttDelay)
                            {
                                dcmDspSvc27InfoPtr->AttemptCounter++;          
                            }
                            if(dcmDspSvc27InfoPtr->AttemptCounter >= secCfgPtr->DcmDspSecurityNumAttDelay)
                            {
                                *ErrorCode = DCM_E_EXCEEDNUMBEROFATTEMPTS;
                                Tm_StartTimer(TmConf_TimerChannel_DcmDspSvc27SecurityDelayTimer, secCfgPtr->DcmDspSecurityDelayTime);
                            }
                            DcmDsl_SetSecurityLevel(DCM_SEC_LEV_LOCKED);
                        }
                        pMsgContext->resDataLen = 1;
                    }

                    break;
                }
            }
        }
    }
    return(retVal);
}

/*******************************************************************************
* -Name            DcmDsp_Svc27_03_Processor
* -Brief           None
* -Details         None
* -Param[in]       OpStatus: The operations status        
* -Param[in, out]  pMsgContext: Message context 
* -Param[out]      ErrorCode: Negative response code
* -Return          E_OK:          
*                  E_NOT_OK: 
*                  DCM_E_PENDING:
*                  DCM_E_FORCE_RCRRP:
*******************************************************************************/
Std_ReturnType DcmDsp_Svc27_03_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
)
{
    Std_ReturnType retVal = E_OK;

    return(retVal);
}

/*******************************************************************************
* -Name            DcmDsp_Svc27_04_Processor
* -Brief           None
* -Details         None
* -Param[in]       OpStatus: The operations status        
* -Param[in, out]  pMsgContext: Message context 
* -Param[out]      ErrorCode: Negative response code
* -Return          E_OK:          
*                  E_NOT_OK: 
*                  DCM_E_PENDING:
*                  DCM_E_FORCE_RCRRP:
*******************************************************************************/
Std_ReturnType DcmDsp_Svc27_04_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
)
{
    Std_ReturnType retVal = E_OK;

    return(retVal);
}


/*******************************************************************************
* -Name            DcmDsp_Svc27_Processor
* -Brief           None
* -Details         None
* -Param[in]       OpStatus: The operations status        
* -Param[in, out]  pMsgContext: Message context 
* -Param[out]      ErrorCode: Negative response code
* -Return          E_OK:          
*                  E_NOT_OK: 
*                  DCM_E_PENDING:
*                  DCM_E_FORCE_RCRRP:
*******************************************************************************/
Std_ReturnType DcmDsp_Svc27_Processor(
    Dcm_ExtendedOpStatusType OpStatus,
    Dcm_MsgContextType* pMsgContext,
    Dcm_NegativeResponseCodeType* ErrorCode
)
{
    Std_ReturnType retVal = E_OK;
    
    return(retVal);
}

